Load in packages
library(tidyverse)
Registered S3 methods overwritten by 'dbplyr':
method from
print.tbl_lazy
print.tbl_sql
── Attaching packages ──────────────────────────────────────────────────────────────────────────────────── tidyverse 1.3.1 ──
✓ ggplot2 3.3.5 ✓ purrr 0.3.4
✓ tibble 3.1.4 ✓ dplyr 1.0.7
✓ tidyr 1.1.3 ✓ stringr 1.4.0
✓ readr 2.0.1 ✓ forcats 0.5.1
── Conflicts ─────────────────────────────────────────────────────────────────────────────────────── tidyverse_conflicts() ──
x dplyr::filter() masks stats::filter()
x dplyr::lag() masks stats::lag()
library(tidyverse)
library(ggplot2)
import data:
find missing data:
No missing data. Check data types of each variable:
str(house)
'data.frame': 21613 obs. of 22 variables:
$ id : num 7.13e+09 6.41e+09 5.63e+09 2.49e+09 1.95e+09 ...
$ date : chr "20141013T000000" "20141209T000000" "20150225T000000" "20141209T000000" ...
$ price : num 221900 538000 180000 604000 510000 ...
$ bedrooms : int 3 3 2 4 3 4 3 3 3 3 ...
$ bathrooms : num 1 2.25 1 3 2 4.5 2.25 1.5 1 2.5 ...
$ sqft_living : int 1180 2570 770 1960 1680 5420 1715 1060 1780 1890 ...
$ sqft_lot : int 5650 7242 10000 5000 8080 101930 6819 9711 7470 6560 ...
$ floors : num 1 2 1 1 1 1 2 1 1 2 ...
$ waterfront : int 0 0 0 0 0 0 0 0 0 0 ...
$ view : int 0 0 0 0 0 0 0 0 0 0 ...
$ condition : int 3 3 3 5 3 3 3 3 3 3 ...
$ grade : int 7 7 6 7 8 11 7 7 7 7 ...
$ sqft_above : int 1180 2170 770 1050 1680 3890 1715 1060 1050 1890 ...
$ sqft_basement: int 0 400 0 910 0 1530 0 0 730 0 ...
$ yr_built : int 1955 1951 1933 1965 1987 2001 1995 1963 1960 2003 ...
$ yr_renovated : int 0 1991 0 0 0 0 0 0 0 0 ...
$ zipcode : int 98178 98125 98028 98136 98074 98053 98003 98198 98146 98038 ...
$ lat : num 47.5 47.7 47.7 47.5 47.6 ...
$ long : num -122 -122 -122 -122 -122 ...
$ sqft_living15: int 1340 1690 2720 1360 1800 4760 2238 1650 1780 2390 ...
$ sqft_lot15 : int 5650 7639 8062 5000 7503 101930 6819 9711 8113 7570 ...
$ num : int 1 1 1 1 1 1 1 1 1 1 ...
We will definitely need to change the data type for the date column, and potentially look into creating factors for some of the more ordinal variables.
Convert date variabe to date type:
Turning view, condition, and grade into ordered factors:
Part 2: EDA
library(gridExtra)
Attaching package: ‘gridExtra’
The following object is masked from ‘package:dplyr’:
combine
names(house)
[1] "id" "date" "price" "bedrooms" "bathrooms" "sqft_living" "sqft_lot"
[8] "floors" "waterfront" "view" "condition" "grade" "sqft_above" "sqft_basement"
[15] "yr_built" "yr_renovated" "zipcode" "lat" "long" "sqft_living15" "sqft_lot15"
[22] "num"
Question: how to deal with indicator (ordinary) varibales in this case? Map to binary classes:



Map to binary classes and check distributions and interactions

Checking possible interactions after mapping categorical variables to a larger classes
##produce the 4 density plots in a 2 by 2 matrix
grid.arrange(sp1, sp2, sp3, sp4, ncol = 2, nrow = 2)
`geom_smooth()` using formula 'y ~ x'
`geom_smooth()` using formula 'y ~ x'
`geom_smooth()` using formula 'y ~ x'
`geom_smooth()` using formula 'y ~ x'

Final check, same scatter plots but with log(price) - no visiable interaction with log price.
##produce the 4 density plots in a 2 by 2 matrix
grid.arrange(sp1, sp2, sp3, sp4, ncol = 2, nrow = 2)
`geom_smooth()` using formula 'y ~ x'
`geom_smooth()` using formula 'y ~ x'
`geom_smooth()` using formula 'y ~ x'
`geom_smooth()` using formula 'y ~ x'

Quantitative pridictors:

Checking how many quantitative observations have 0 values
colSums(house[,quant_vars] == 0)
yr_built yr_renovated floors bedrooms bathrooms sqft_living sqft_lot sqft_above
0 20699 0 13 10 0 0 0
sqft_basement sqft_living15 sqft_lot15
13126 0 0
Probably some homes have no basements and thus zeros sqft_basement is okay, but all homes are expected to have non-zero number of bedrooms (13 zeros) and bathrooms (10 zeroz). Drop these rows:
colSums(house[,quant_vars] == 0)
yr_built yr_renovated floors bedrooms bathrooms sqft_living sqft_lot sqft_above
0 20683 0 0 0 0 0 0
sqft_basement sqft_living15 sqft_lot15
13110 0 0
Converting quantitative predictor floors to a factor 1, 2, 3.
grid.arrange(sp_floors, bp_floors, ncol = 2, nrow = 1)
`geom_smooth()` using formula 'y ~ x'

Computing age of the house and removing year_build and year_renovated
names(house)
[1] "price" "bedrooms" "bathrooms" "sqft_living" "sqft_lot" "floors" "waterfront"
[8] "view" "condition" "grade" "sqft_above" "sqft_basement" "sqft_living15" "sqft_lot15"
[15] "age"
Final set of quantitative vars:
hist.data.frame(house[,quant_vars])
click left mouse button to proceed

Correlations of quantitative vars:
ggcorrplot(corr,
method = "circle",
lab = TRUE,
# type = "lower",
outline.color = "white",
ggtheme = ggplot2::theme_gray,
colors = c("#6D9EC1", "white", "#E46726"))
Warning: `guides(<scale> = FALSE)` is deprecated. Please use `guides(<scale> = "none")` instead.

Questions: floors 1, 2, 3 as factors?
N/A in sqft_basement
Will removing outliers help with Residuals/Fitted values
str(house)
'data.frame': 21597 obs. of 15 variables:
$ price : num 221900 538000 180000 604000 510000 ...
$ bedrooms : int 3 3 2 4 3 4 3 3 3 3 ...
$ bathrooms : num 1 2.25 1 3 2 4.5 2.25 1.5 1 2.5 ...
$ sqft_living : int 1180 2570 770 1960 1680 5420 1715 1060 1780 1890 ...
$ sqft_lot : int 5650 7242 10000 5000 8080 101930 6819 9711 7470 6560 ...
$ floors : Factor w/ 3 levels "1","2","3": 1 2 1 1 1 1 2 1 1 2 ...
$ waterfront : Ord.factor w/ 2 levels "0"<"1": 1 1 1 1 1 1 1 1 1 1 ...
$ view : Factor w/ 2 levels "0","1": 1 1 1 1 1 1 1 1 1 1 ...
$ condition : Factor w/ 2 levels "0","1": 1 1 1 2 1 1 1 1 1 1 ...
$ grade : Factor w/ 2 levels "0","1": 1 1 2 1 2 2 1 1 1 1 ...
$ sqft_above : int 1180 2170 770 1050 1680 3890 1715 1060 1050 1890 ...
$ sqft_basement: int 0 400 0 910 0 1530 0 0 730 0 ...
$ sqft_living15: int 1340 1690 2720 1360 1800 4760 2238 1650 1780 2390 ...
$ sqft_lot15 : int 5650 7639 8062 5000 7503 101930 6819 9711 8113 7570 ...
$ age : num 66 30 88 56 34 20 26 58 61 18 ...
LS0tCnRpdGxlOiAnU1RBVCA2MDIxOiBQcm9qZWN0IDInCmF1dGhvcjogIkNvbm5pZSBDdWkiCmRhdGU6ICIxMS8yNi8yMDIxIgpvdXRwdXQ6CiAgaHRtbF9kb2N1bWVudDoKICAgIGRmX3ByaW50OiBwYWdlZAogIGh0bWxfbm90ZWJvb2s6IGRlZmF1bHQKLS0tCgoKTG9hZCBpbiBwYWNrYWdlcwpgYGB7cn0KbGlicmFyeSh0aWR5dmVyc2UpCmxpYnJhcnkoZ2dwbG90MikKYGBgCmltcG9ydCBkYXRhOgpgYGB7cn0KaG91c2UgPC0gcmVhZC5jc3YoImhvdXNlX2RhdGEuY3N2IikKaGVhZChob3VzZSkKYGBgCmZpbmQgbWlzc2luZyBkYXRhOgpgYGB7cn0KIyBsaXN0IHJvd3Mgb2YgZGF0YSB0aGF0IGhhdmUgbWlzc2luZyB2YWx1ZXMKaG91c2VbIWNvbXBsZXRlLmNhc2VzKGhvdXNlKSxdCmBgYApObyBtaXNzaW5nIGRhdGEuCkNoZWNrIGRhdGEgdHlwZXMgb2YgZWFjaCB2YXJpYWJsZToKYGBge3J9CnN0cihob3VzZSkKYGBgCldlIHdpbGwgZGVmaW5pdGVseSBuZWVkIHRvIGNoYW5nZSB0aGUgZGF0YSB0eXBlIGZvciB0aGUgZGF0ZSBjb2x1bW4sIGFuZCBwb3RlbnRpYWxseSBsb29rIGludG8gY3JlYXRpbmcgZmFjdG9ycyBmb3Igc29tZSBvZiB0aGUgbW9yZSBvcmRpbmFsIHZhcmlhYmxlcy4KYGBge3J9CmhvdXNlJGRhdGUgPSBzdWJzdHIoaG91c2UkZGF0ZSwxLG5jaGFyKGhvdXNlJGRhdGUpLTcpCmhlYWQoaG91c2UpCmBgYApDb252ZXJ0IGRhdGUgdmFyaWFiZSB0byBkYXRlIHR5cGU6CmBgYHtyfQpob3VzZSRkYXRlIDwtIGFzLkRhdGUoaG91c2UkZGF0ZSwgIiVZJW0lZCIpCmhlYWQoaG91c2UpCmBgYApUdXJuaW5nIHZpZXcsIGNvbmRpdGlvbiwgYW5kIGdyYWRlIGludG8gb3JkZXJlZCBmYWN0b3JzOgpgYGB7cn0KaG91c2UkdmlldyA8LSBmYWN0b3IoaG91c2Ukdmlldywgb3JkZXJlZCA9IFRSVUUsIGxldmVscyA9IGMoMCwgMSwgMiwgMywgNCkpCmhvdXNlJGNvbmRpdGlvbiA8LSBmYWN0b3IoaG91c2UkY29uZGl0aW9uLCBvcmRlcmVkID0gVFJVRSwgbGV2ZWxzID0gYygxLCAyLCAzLCA0LCA1KSkKaG91c2UkZ3JhZGUgPC0gZmFjdG9yKGhvdXNlJGdyYWRlLCBvcmRlcmVkID0gVFJVRSwgbGV2ZWxzID0gYygxLCAyLCAzLCA0LCA1LCA2LCA3LCA4LCA5LCAxMCwgMTEsIDEyLCAxMywgMTQsIDE1KSkKaG91c2Ukd2F0ZXJmcm9udCA8LSBmYWN0b3IoaG91c2Ukd2F0ZXJmcm9udCwgb3JkZXJlZCA9IFRSVUUsIGxldmVscyA9IGMoMCwgMSkpCmBgYAoKCiMjIFBhcnQgMjogRURBCgpgYGB7cn0KI2luc3RhbGwucGFja2FnZXMoImdnY29ycnBsb3QiKQojaW5zdGFsbC5wYWNrYWdlcygibWlzY3NldCIpCiNsaWJyYXJ5KG1pc2NzZXQpCiNsaWJyYXJ5KEhtaXNjKQpsaWJyYXJ5KHRpZHl2ZXJzZSkKbGlicmFyeShkcGx5cikKbGlicmFyeShmYXJhd2F5KQpsaWJyYXJ5KGdyaWRFeHRyYSkKYGBgCgpgYGB7cn0KbmFtZXMoaG91c2UpCmBgYAoKIyMjIyBQcmlvciB0byBkcm9wcGluZyBEYXRlIGFuZCBHZW90YWdzIGNvbnNpZGVyIHVzaW5nIHRoZW0gZm9yIHBsb3R0aW5nLCBmb3IgZXhhbXBsZSB0cmFuc2FjdGlvbiBjb3VudHMgYnkgZGF0ZXM/CgoKYGBge3J9CmhvdXNlIDwtIHN1YnNldChob3VzZSwgc2VsZWN0PS1jKGlkLG51bSwgZGF0ZSwgemlwY29kZSwgbGF0LCBsb25nKSkKbmFtZXMoaG91c2UpCmBgYAoKYGBge3J9CiNkZXNjcmliZShob3VzZSkKYGBgCgoKU3VtbWFyeSBwbG90czoKYGBge3J9CnNwMSA8LSBnZ3Bsb3QoaG91c2UsIGFlcyh4PXNxZnRfbGl2aW5nLCB5PXByaWNlLCBjb2xvcj13YXRlcmZyb250KSkrCiAgZ2VvbV9wb2ludCgpKwogIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsbSIsIHNlPUZBTFNFKSsKICBsYWJzKHg9InNxZnRfbGl2aW5nIiwgCiAgICAgICB5PSJwcmljZSIsCiAgICAgICB0aXRsZT0iU2NhdHRlciBwbG90IG9mIHByaWNlIGFnYWluc3Qgc3FmdF9saXZpbmcgd2l0aCB3YXRlcmZvcm50IGluZGljYXRvciIpCgpzcDIgPC0gZ2dwbG90KGhvdXNlLCBhZXMoeD1zcWZ0X2xpdmluZywgeT1wcmljZSwgY29sb3I9dmlldykpKwogIGdlb21fcG9pbnQoKSsKICBnZW9tX3Ntb290aChtZXRob2QgPSAibG0iLCBzZT1GQUxTRSkrCiAgbGFicyh4PSJzcWZ0X2xpdmluZyIsIAogICAgICAgeT0icHJpY2UiLAogICAgICAgdGl0bGU9IlNjYXR0ZXIgcGxvdCBvZiBwcmljZSBhZ2FpbnN0IHNxZnRfbGl2aW5nIHdpdGggdmlldyBpbmRpY2F0b3IiKQogIAogIApzcDMgPC0gZ2dwbG90KGhvdXNlLCBhZXMoeD1zcWZ0X2xpdmluZywgeT1wcmljZSwgY29sb3I9Y29uZGl0aW9uKSkrCiAgZ2VvbV9wb2ludCgpKwogIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsbSIsIHNlPUZBTFNFKSsKICBsYWJzKHg9InNxZnRfbGl2aW5nIiwgCiAgICAgICB5PSJwcmljZSIsCiAgICAgICB0aXRsZT0iU2NhdHRlciBwbG90IG9mIHByaWNlIGFnYWluc3Qgc3FmdF9saXZpbmcgd2l0aCBjb25kaXRpb24gaW5kaWNhdG9yIikKICAKICAKICAKc3A0IDwtIGdncGxvdChob3VzZSwgYWVzKHg9c3FmdF9saXZpbmcsIHk9cHJpY2UsIGNvbG9yPWdyYWRlKSkrCiAgZ2VvbV9wb2ludCgpKwogIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsbSIsIHNlPUZBTFNFKSsKICBsYWJzKHg9InNxZnRfbGl2aW5nIiwgCiAgICAgICB5PSJwcmljZSIsCiAgICAgICB0aXRsZT0iU2NhdHRlciBwbG90IG9mIHByaWNlIGFnYWluc3Qgc3FmdF9saXZpbmcgd2l0aCBncmFkZSBpbmRpY2F0b3IiKQoKIyNwcm9kdWNlIHRoZSA0IGRlbnNpdHkgcGxvdHMgaW4gYSAyIGJ5IDIgbWF0cml4CmdyaWQuYXJyYW5nZShzcDEsIHNwMiwgc3AzLCBzcDQsIG5jb2wgPSAyLCBucm93ID0gMikKYGBgCgoKIyMjIyBRdWVzdGlvbjogaG93IHRvIGRlYWwgd2l0aCBpbmRpY2F0b3IgKG9yZGluYXJ5KSB2YXJpYmFsZXMgaW4gdGhpcyBjYXNlPyBNYXAgdG8gYmluYXJ5IGNsYXNzZXM6CgpgYGB7cn0KY2F0X3ZhcnMgPSBjKCJ3YXRlcmZyb250IiwgInZpZXciLCAiY29uZGl0aW9uIiwgImdyYWRlIikKYGBgCgpgYGB7cn0KZ2dwbG90R3JpZChuY29sID0gMiwKICBsYXBwbHkoYygidmlldyIsICJ3YXRlcmZyb250IiwgImNvbmRpdGlvbiIsICJncmFkZSIpLAogICAgZnVuY3Rpb24oY29sKSB7CiAgICAgICAgZ2dwbG90KGhvdXNlLCBhZXNfc3RyaW5nKGNvbCkpICsgZ2VvbV9iYXIoKSArIGNvb3JkX2ZsaXAoKQogICAgfSkpCmBgYAoKYGBge3J9CmJwMSA8LSBnZ3Bsb3QoaG91c2UsIGFlcyh4PXdhdGVyZnJvbnQsIHk9cHJpY2UpKSsKZ2VvbV9ib3hwbG90KCkrCmxhYnMoeD0id2F0ZXJmcm9udCIsIHk9InByaWNlIiwgdGl0bGU9IlByaWNlIGJ5IHdhdGVyZnJvbnQiKQoKYnAyIDwtIGdncGxvdChob3VzZSwgYWVzKHg9dmlldywgeT1wcmljZSkpKwpnZW9tX2JveHBsb3QoKSsKbGFicyh4PSJ2aWV3IiwgeT0icHJpY2UiLCB0aXRsZT0iUHJpY2UgYnkgdmlldyIpCgpicDMgPC0gZ2dwbG90KGhvdXNlLCBhZXMoeD1jb25kaXRpb24sIHk9cHJpY2UpKSsKZ2VvbV9ib3hwbG90KCkrCmxhYnMoeD0iY29uZGl0aW9uIiwgeT0icHJpY2UiLCB0aXRsZT0iUHJpY2UgYnkgY29uZGl0aW9uIikKCmJwNCA8LSBnZ3Bsb3QoaG91c2UsIGFlcyh4PWdyYWRlLCB5PXByaWNlKSkrCmdlb21fYm94cGxvdCgpKwpsYWJzKHg9ImdyYWRlIiwgeT0icHJpY2UiLCB0aXRsZT0iUHJpY2UgYnkgZ3JhZGUiKQoKIyNwcm9kdWNlIHRoZSA0IGRlbnNpdHkgcGxvdHMgaW4gYSAyIGJ5IDIgbWF0cml4CmdyaWQuYXJyYW5nZShicDEsIGJwMiwgYnAzLCBicDQsIG5jb2wgPSAyLCBucm93ID0gMikKYGBgCgojIyMjIE1hcCB0byBiaW5hcnkgY2xhc3NlcyBhbmQgY2hlY2sgZGlzdHJpYnV0aW9ucyBhbmQgaW50ZXJhY3Rpb25zCgpgYGB7cn0KIyBDaGFuZ2luZyBgdmlld2AgdG8gMCBmb3IgcmVndWxhciB2aWV3IGFuZCAxIGZvciBldmVyeSBvdGhlciB2aWV3CmhvdXNlJHZpZXcgPC0gZmFjdG9yKGlmZWxzZShob3VzZSR2aWV3IT0wLCAxLCAwKSkKIyBDaGFuZ2luZyBgY29uZGl0aW9uYCB0byAwIGZvciBldmVyeXRoaW5nIGJlbG93IDMgYW5kIDEgb3RoZXJ3aXNlCmhvdXNlJGNvbmRpdGlvbiA8LSBmYWN0b3IoaWZlbHNlKGhvdXNlJGNvbmRpdGlvbj09MSB8IGhvdXNlJGNvbmRpdGlvbj09MiB8IGhvdXNlJGNvbmRpdGlvbj09MywgMCwgMSkpCiMgQ2hhbmdpbmcgYGdyYWRlYCB0byAwIGZvciBldmVyeXRoaW5nIGJlbG93IDcgYW5kIDEgb3RoZXJ3aXNlCmhvdXNlJGdyYWRlIDwtIGZhY3RvcihpZmVsc2UoaG91c2UkZ3JhZGU9PTEgfCBob3VzZSRncmFkZT09MiB8IGhvdXNlJGdyYWRlPT0zIHwKICAgICAgICAgICAgICAgICAgICAgIGhvdXNlJGdyYWRlPT00IHwgaG91c2UkZ3JhZGU9PTUgfCBob3VzZSRncmFkZT09NyAsIDAsIDEpKQpgYGAKCgpgYGB7cn0KZ2dwbG90R3JpZChuY29sID0gMiwKICBsYXBwbHkoYygidmlldyIsICJ3YXRlcmZyb250IiwgImNvbmRpdGlvbiIsICJncmFkZSIpLAogICAgZnVuY3Rpb24oY29sKSB7CiAgICAgICAgZ2dwbG90KGhvdXNlLCBhZXNfc3RyaW5nKGNvbCkpICsgZ2VvbV9iYXIoKSArIGNvb3JkX2ZsaXAoKQogICAgfSkpCmBgYAoKIyMjIyBDaGVja2luZyBwb3NzaWJsZSBpbnRlcmFjdGlvbnMgYWZ0ZXIgbWFwcGluZyBjYXRlZ29yaWNhbCB2YXJpYWJsZXMgdG8gYSBsYXJnZXIgY2xhc3NlcwoKCmBgYHtyfQpzcDEgPC0gZ2dwbG90KGhvdXNlLCBhZXMoeD1zcWZ0X2xpdmluZywgeT1wcmljZSwgY29sb3I9d2F0ZXJmcm9udCkpKwogIGdlb21fcG9pbnQoKSsKICBnZW9tX3Ntb290aChtZXRob2QgPSAibG0iLCBzZT1GQUxTRSkrCiAgbGFicyh4PSJzcWZ0X2xpdmluZyIsIAogICAgICAgeT0icHJpY2UiLAogICAgICAgdGl0bGU9IlNjYXR0ZXIgcGxvdCBvZiBwcmljZSBhZ2FpbnN0IHNxZnRfbGl2aW5nIHdpdGggd2F0ZXJmb3JudCBpbmRpY2F0b3IiKQoKc3AyIDwtIGdncGxvdChob3VzZSwgYWVzKHg9c3FmdF9saXZpbmcsIHk9cHJpY2UsIGNvbG9yPXZpZXcpKSsKICBnZW9tX3BvaW50KCkrCiAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxtIiwgc2U9RkFMU0UpKwogIGxhYnMoeD0ic3FmdF9saXZpbmciLCAKICAgICAgIHk9InByaWNlIiwKICAgICAgIHRpdGxlPSJTY2F0dGVyIHBsb3Qgb2YgcHJpY2UgYWdhaW5zdCBzcWZ0X2xpdmluZyB3aXRoIHZpZXcgaW5kaWNhdG9yIikKICAKc3AzIDwtIGdncGxvdChob3VzZSwgYWVzKHg9c3FmdF9saXZpbmcsIHk9cHJpY2UsIGNvbG9yPWNvbmRpdGlvbikpKwogIGdlb21fcG9pbnQoKSsKICBnZW9tX3Ntb290aChtZXRob2QgPSAibG0iLCBzZT1GQUxTRSkrCiAgbGFicyh4PSJzcWZ0X2xpdmluZyIsIAogICAgICAgeT0icHJpY2UiLAogICAgICAgdGl0bGU9IlNjYXR0ZXIgcGxvdCBvZiBwcmljZSBhZ2FpbnN0IHNxZnRfbGl2aW5nIHdpdGggY29uZGl0aW9uIGluZGljYXRvciIpCiAgCnNwNCA8LSBnZ3Bsb3QoaG91c2UsIGFlcyh4PXNxZnRfbGl2aW5nLCB5PXByaWNlLCBjb2xvcj1ncmFkZSkpKwogIGdlb21fcG9pbnQoKSsKICBnZW9tX3Ntb290aChtZXRob2QgPSAibG0iLCBzZT1GQUxTRSkrCiAgbGFicyh4PSJzcWZ0X2xpdmluZyIsIAogICAgICAgeT0icHJpY2UiLAogICAgICAgdGl0bGU9IlNjYXR0ZXIgcGxvdCBvZiBwcmljZSBhZ2FpbnN0IHNxZnRfbGl2aW5nIHdpdGggZ3JhZGUgaW5kaWNhdG9yIikKCiMjcHJvZHVjZSB0aGUgNCBkZW5zaXR5IHBsb3RzIGluIGEgMiBieSAyIG1hdHJpeApncmlkLmFycmFuZ2Uoc3AxLCBzcDIsIHNwMywgc3A0LCBuY29sID0gMiwgbnJvdyA9IDIpCgpgYGAKCiMjIyMgRmluYWwgY2hlY2ssIHNhbWUgc2NhdHRlciBwbG90cyBidXQgd2l0aCBsb2cocHJpY2UpIC0gbm8gdmlzaWFibGUgaW50ZXJhY3Rpb24gd2l0aCBsb2cgcHJpY2UuCgpgYGB7cn0Kc3AxIDwtIGdncGxvdChob3VzZSwgYWVzKHg9c3FmdF9saXZpbmcsIHk9bG9nKHByaWNlKSwgY29sb3I9d2F0ZXJmcm9udCkpKwogIGdlb21fcG9pbnQoKSsKICBnZW9tX3Ntb290aChtZXRob2QgPSAibG0iLCBzZT1GQUxTRSkrCiAgbGFicyh4PSJzcWZ0X2xpdmluZyIsIAogICAgICAgeT0icHJpY2UiLAogICAgICAgdGl0bGU9IlNjYXR0ZXIgcGxvdCBvZiBwcmljZSBhZ2FpbnN0IHNxZnRfbGl2aW5nIHdpdGggd2F0ZXJmb3JudCBpbmRpY2F0b3IiKQoKc3AyIDwtIGdncGxvdChob3VzZSwgYWVzKHg9c3FmdF9saXZpbmcsIHk9bG9nKHByaWNlKSwgY29sb3I9dmlldykpKwogIGdlb21fcG9pbnQoKSsKICBnZW9tX3Ntb290aChtZXRob2QgPSAibG0iLCBzZT1GQUxTRSkrCiAgbGFicyh4PSJzcWZ0X2xpdmluZyIsIAogICAgICAgeT0icHJpY2UiLAogICAgICAgdGl0bGU9IlNjYXR0ZXIgcGxvdCBvZiBwcmljZSBhZ2FpbnN0IHNxZnRfbGl2aW5nIHdpdGggdmlldyBpbmRpY2F0b3IiKQogIAogIApzcDMgPC0gZ2dwbG90KGhvdXNlLCBhZXMoeD1zcWZ0X2xpdmluZywgeT1sb2cocHJpY2UpLCBjb2xvcj1jb25kaXRpb24pKSsKICBnZW9tX3BvaW50KCkrCiAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxtIiwgc2U9RkFMU0UpKwogIGxhYnMoeD0ic3FmdF9saXZpbmciLCAKICAgICAgIHk9InByaWNlIiwKICAgICAgIHRpdGxlPSJTY2F0dGVyIHBsb3Qgb2YgcHJpY2UgYWdhaW5zdCBzcWZ0X2xpdmluZyB3aXRoIGNvbmRpdGlvbiBpbmRpY2F0b3IiKQogIApzcDQgPC0gZ2dwbG90KGhvdXNlLCBhZXMoeD1zcWZ0X2xpdmluZywgeT1sb2cocHJpY2UpLCBjb2xvcj1ncmFkZSkpKwogIGdlb21fcG9pbnQoKSsKICBnZW9tX3Ntb290aChtZXRob2QgPSAibG0iLCBzZT1GQUxTRSkrCiAgbGFicyh4PSJzcWZ0X2xpdmluZyIsIAogICAgICAgeT0icHJpY2UiLAogICAgICAgdGl0bGU9IlNjYXR0ZXIgcGxvdCBvZiBwcmljZSBhZ2FpbnN0IHNxZnRfbGl2aW5nIHdpdGggZ3JhZGUgaW5kaWNhdG9yIikKCiMjcHJvZHVjZSB0aGUgNCBkZW5zaXR5IHBsb3RzIGluIGEgMiBieSAyIG1hdHJpeApncmlkLmFycmFuZ2Uoc3AxLCBzcDIsIHNwMywgc3A0LCBuY29sID0gMiwgbnJvdyA9IDIpCgpgYGAKCiMjIyMgUXVhbnRpdGF0aXZlIHByaWRpY3RvcnM6CgpgYGB7cn0KCnF1YW50X3ZhcnMgPSBjKCJ5cl9idWlsdCIsICJ5cl9yZW5vdmF0ZWQiLAogICAgICAgICAgICAgICAiZmxvb3JzIiwgImJlZHJvb21zIiwgImJhdGhyb29tcyIsIAogICAgICAgICAgICAgICAic3FmdF9saXZpbmciLCAic3FmdF9sb3QiLCAic3FmdF9hYm92ZSIsICJzcWZ0X2Jhc2VtZW50IiwgCiAgICAgICAgICAgICAgICJzcWZ0X2xpdmluZzE1IiwgInNxZnRfbG90MTUiKQoKbGlicmFyeShIbWlzYykKaGlzdC5kYXRhLmZyYW1lKGhvdXNlWyxxdWFudF92YXJzXSkKCmBgYAoKIyMjIyBDaGVja2luZyBob3cgbWFueSBxdWFudGl0YXRpdmUgb2JzZXJ2YXRpb25zIGhhdmUgMCB2YWx1ZXMKCmBgYHtyfQpjb2xTdW1zKGhvdXNlWyxxdWFudF92YXJzXSA9PSAwKQpgYGAKCgojIyMjIFByb2JhYmx5IHNvbWUgaG9tZXMgaGF2ZSBubyBiYXNlbWVudHMgYW5kIHRodXMgemVyb3Mgc3FmdF9iYXNlbWVudCBpcyBva2F5LCBidXQgYWxsIGhvbWVzIGFyZSBleHBlY3RlZCB0byBoYXZlIG5vbi16ZXJvIG51bWJlciBvZiBiZWRyb29tcyAoMTMgemVyb3MpIGFuZCBiYXRocm9vbXMgKDEwIHplcm96KS4gRHJvcCB0aGVzZSByb3dzOgoKCmBgYHtyfQpob3VzZSA8LSBmaWx0ZXIoaG91c2UsIGJhdGhyb29tcyAhPSAwLCBiZWRyb29tcyAhPSAwKQpjb2xTdW1zKGhvdXNlWyxxdWFudF92YXJzXSA9PSAwKQpgYGAKCgojIyMjIENvbnZlcnRpbmcgcXVhbnRpdGF0aXZlIHByZWRpY3RvciBmbG9vcnMgdG8gYSBmYWN0b3IgMSwgMiwgMy4KCgpgYGB7cn0KaG91c2UkZmxvb3JzIDwtIGZhY3RvcihpZmVsc2UoaG91c2UkZmxvb3JzIDwgMiwgMSwgaWZlbHNlKGhvdXNlJGZsb29ycyA8IDMsIDIsIGlmZWxzZShob3VzZSRmbG9vcnM+PTMsIDMsIDApKSkpCgpzcF9mbG9vcnMgPC0gZ2dwbG90KGhvdXNlLCBhZXMoeD1zcWZ0X2xpdmluZywgeT1wcmljZSwgY29sb3I9Zmxvb3JzKSkrCiAgZ2VvbV9wb2ludCgpKwogIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsbSIsIHNlPUZBTFNFKSsKICBsYWJzKHg9InNxZnRfbGl2aW5nIiwgCiAgICAgICB5PSJwcmljZSIsCiAgICAgICB0aXRsZT0iU2NhdHRlciBwbG90IG9mIHByaWNlIGFnYWluc3Qgc3FmdF9saXZpbmcgd2l0aCBmbG9vcnMgaW5kaWNhdG9yIikKCmJwX2Zsb29ycyA8LSBnZ3Bsb3QoaG91c2UsIGFlcyh4PWZsb29ycywgeT1wcmljZSkpKwogIGdlb21fYm94cGxvdCgpKwogIGxhYnMoeD0iZmxvb3JzIiwgeT0icHJpY2UiLCB0aXRsZT0iUHJpY2UgYnkgbnVtYmVyIG9mIGZsb29ycyIpCgpncmlkLmFycmFuZ2Uoc3BfZmxvb3JzLCBicF9mbG9vcnMsIG5jb2wgPSAyLCBucm93ID0gMSkKYGBgCgoKIyMjIyBDb21wdXRpbmcgYWdlIG9mIHRoZSBob3VzZSBhbmQgcmVtb3ZpbmcgeWVhcl9idWlsZCBhbmQgeWVhcl9yZW5vdmF0ZWQKCmBgYHtyfQpob3VzZSRhZ2UgPSBpZmVsc2UoMjAyMS1ob3VzZSR5cl9yZW5vdmF0ZWQgPj0gMjAyMS1ob3VzZSR5cl9idWlsdCwgMjAyMS1ob3VzZSR5cl9idWlsdCwgMjAyMS1ob3VzZSR5cl9yZW5vdmF0ZWQpCmhlYWQoaG91c2UpCmBgYAoKYGBge3J9CmhvdXNlIDwtIHN1YnNldChob3VzZSwgc2VsZWN0PS1jKHlyX3Jlbm92YXRlZCwgeXJfYnVpbHQpKQpuYW1lcyhob3VzZSkKYGBgCgoKIyMjIyBGaW5hbCBzZXQgb2YgcXVhbnRpdGF0aXZlIHZhcnM6CgpgYGB7cn0KcXVhbnRfdmFycyA9IGMoImFnZSIsICJiZWRyb29tcyIsICJiYXRocm9vbXMiLCAKICAgICAgICAgICAgICAgInNxZnRfbGl2aW5nIiwgInNxZnRfbG90IiwgInNxZnRfYWJvdmUiLCAic3FmdF9iYXNlbWVudCIsIAogICAgICAgICAgICAgICAic3FmdF9saXZpbmcxNSIsICJzcWZ0X2xvdDE1IikKCmhpc3QuZGF0YS5mcmFtZShob3VzZVsscXVhbnRfdmFyc10pCgpgYGAKICAgICAgICAgICAgICAgCiMjIyMgQ29ycmVsYXRpb25zIG9mIHF1YW50aXRhdGl2ZSB2YXJzOgoKYGBge3J9CmNvcnIgPC0gcm91bmQoY29yKGhvdXNlWyxjKCJwcmljZSIscXVhbnRfdmFycyldKSwgMSkKbGlicmFyeShnZ2NvcnJwbG90KQpnZ2NvcnJwbG90KGNvcnIsIAogICAgICAgICAgIG1ldGhvZCA9ICJjaXJjbGUiLCAKICAgICAgICAgICBsYWIgPSBUUlVFLAogICAgICAgICAgIyB0eXBlID0gImxvd2VyIiwgCiAgICAgICAgICAgb3V0bGluZS5jb2xvciA9ICJ3aGl0ZSIsIAogICAgICAgICAgIGdndGhlbWUgPSBnZ3Bsb3QyOjp0aGVtZV9ncmF5LAogICAgICAgICAgIGNvbG9ycyA9IGMoIiM2RDlFQzEiLCAid2hpdGUiLCAiI0U0NjcyNiIpKQpgYGAKCgoKCgojIyBUT0RPOiBpbnRlcnByZXRpbmcgbW9kZWxzIGh0dHBzOi8vY3Jhbi5yLXByb2plY3Qub3JnL3dlYi9wYWNrYWdlcy9qdG9vbHMvdmlnbmV0dGVzL3N1bW0uaHRtbAoKYGBge3J9CmZpdCA8LSBsbShsb2cocHJpY2UpIH4gLiAsIGRhdGEgPSBob3VzZSkKc3VtbWFyeShmaXQpCmBgYAoKYGBge3J9CnBsb3QoZml0KQpgYGAKCgpgYGB7cn0KZml0X2xlcy5zcWZ0X2Jhc2VtZW50IDwtIGxtKGxvZyhwcmljZSkgfiAuIC0gc3FmdF9iYXNlbWVudCwgZGF0YSA9IGhvdXNlKQpzdW1tYXJ5KGZpdF9sZXMuc3FmdF9iYXNlbWVudCkKYGBgCgpgYGB7cn0KcGxvdChmaXRfbGVzLnNxZnRfYmFzZW1lbnQpCmBgYAoKIyBRdWVzdGlvbnM6IGZsb29ycyAxLCAyLCAzIGFzIGZhY3RvcnM/CiMgTi9BIGluIHNxZnRfYmFzZW1lbnQKIyBXaWxsIHJlbW92aW5nIG91dGxpZXJzIGhlbHAgd2l0aCBSZXNpZHVhbHMvRml0dGVkIHZhbHVlcwoKYGBge3J9CnN0cihob3VzZSkKYGBgCgoKCgoKCgoK